package org.iris.plugin.model

import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
import net.mamoe.mirai.contact.User
import net.mamoe.mirai.contact.UserOrBot
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.Image.Key.queryUrl
import org.iris.plugin.HitHit
import org.iris.plugin.HitHit.tmp
import org.iris.plugin.util.GIFEncoder
import java.awt.AlphaComposite
import java.awt.Color
import java.awt.RenderingHints
import java.awt.geom.RoundRectangle2D
import java.awt.image.BufferedImage
import java.io.File
import java.net.URL
import javax.imageio.ImageIO
import java.awt.Image as AwtImage

@Suppress("SameParameterValue")
object HitHitTool {

    suspend fun getImage(action: Action, user:User, image: Image, delay: Int) {
        val imageFromServer = URL(image.queryUrl())
        mkImg(action, URL(user.avatarUrl), imageFromServer, tmp.resolve("${user.id}_${image.imageId}_$action.gif"), delay)
    }

    fun getAction(action: Action, send: UserOrBot, target: User, delay: Int) {
        val qqId = send.id

        if (!tmp.exists()) tmp.mkdir()
        if (tmp.resolve("${qqId}_${target.id}_$action.gif").exists()) return
        val avatar = URL(send.avatarUrl)
        val targetAvatar = URL(target.avatarUrl)
        mkImg(action, avatar, targetAvatar, tmp.resolve("${qqId}_${target.id}_$action.gif"), delay)
    }

    private fun mkImg(action: Action, send: URL, target: URL, savePath: File, delay: Int) {
        val posList = POS_MAP[action]
        val images: ArrayList<BufferedImage> = arrayListOf()
        val avatarList =
            if (INTERACT_MAP[action]!!) listOf(send, target) else listOf(target)

        // 读取背景图片
        for (i in posList!!.indices) {
            val paths = IMAGE_MAP[action]!!.split(".")
            val bg = ImageIO.read(HitHit.javaClass.getResourceAsStream("/data/HitHit/${paths[0]}${i+1}.${paths[1]}"))
            images.add(bg)
        }

        for (i in avatarList.indices.reversed()) {
            val avatarImage = ImageIO.read(avatarList[i])
            val targetSize = avatarImage.width
            val roundImage = BufferedImage(targetSize, targetSize, BufferedImage.TYPE_INT_ARGB)
            roundImage.createGraphics().apply {
                composite = AlphaComposite.Src
                setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
                color = Color.WHITE
                fill(
                    RoundRectangle2D.Float(
                        0F, 0F, targetSize.toFloat(), targetSize.toFloat(),
                        targetSize.toFloat(), targetSize.toFloat()
                    )
                )
                composite = AlphaComposite.SrcAtop
                drawImage(avatarImage, 0, 0, targetSize, targetSize, null)
                dispose()
            }

            for (j in posList.indices) {
                roundImage.getScaledInstance(images[j].width, images[j].height, BufferedImage.SCALE_SMOOTH).apply {
                    images[j] = processImage(this, images[j], posList[j][0 + 4 * i], posList[j][1 + 4 * i], posList[j][2 + 4 * i], posList[j][3 + 4 * i], UNDERBG_MAP[action]!!)
                }
            }
        }

        GIFEncoder.convert(images, "$savePath", delay)
    }


    //w: 宽 h: 高 x,y: 头像位置 bg:背景图片 underBG:图片是否画在背景下面
    @OptIn(ExperimentalCommandDescriptors::class, ConsoleExperimentalApi::class)
    private fun processImage(
        image: AwtImage,
        bg: BufferedImage,
        x: Int,
        y: Int,
        w: Int,
        h: Int,
        underBG: Boolean = false
    ): BufferedImage {
        val processingImage = BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB)
        val processedImage = BufferedImage(bg.width, bg.height, BufferedImage.TYPE_INT_RGB)
        processingImage.createGraphics().apply {
            drawImage(image, 0, 0, w, h, null)
            dispose()
        }
        processedImage.createGraphics().apply {
            color = Color.WHITE
            fillRect(0, 0, bg.width, bg.height)
            if (underBG) {
                // 后绘制背景
                drawImage(processingImage, x, y, null)
                drawImage(bg, 0, 0, null)
            }
            else {
                // 先绘制背景
                drawImage(bg, 0, 0, null)
                drawImage(processingImage, x, y, null)
            }
            dispose()
        }
        return processedImage
    }

/*
@ConsoleExperimentalApi
@ExperimentalCommandDescriptors
private fun selfRead(i: Int): InputStream {
    val path = PatPat.javaClass.protectionDomain.codeSource.location.path
    val jarPath = JarFile(path)
    val entry = jarPath.getJarEntry("data/PatPat/img${i}.png")
    return jarPath.getInputStream(entry)
}
 */
}